#region License, Terms and Conditions
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 */
#endregion

using System;
using System.Linq;
using System.Text;
using System.Web;
using System.Collections.Generic;
using raya.Library;

namespace raya.Models.widgets
{
    public class TagCloud : Model
    {
        public TagCloud(tagType type)
        {
            ttype = type;
            SortList(ttype);
        }
        public enum tagType
        {
            product,
            blog
        }

        private readonly tagType ttype;
        private struct tagCount
        {
            public string name;
            public int count;
        } 
        private const string LINK = "<a href=\"{0}\" class=\"{1}\" title=\"{2}\">{3}</a> ";
        private readonly Dictionary<string, string> _WeightedList = new Dictionary<string, string>();

        private int _MinimumPosts = 1;

        public int MinimumPosts
        {
            get { return _MinimumPosts; }
            set { _MinimumPosts = value; }
        }

        /// <summary>
        /// Builds a raw list of all tags and the number of times
        /// they have been added to a post.
        /// </summary>
        private static SortedDictionary<string, int> CreateRawList(tagType type)
        {
            SortedDictionary<string, int> dic = new SortedDictionary<string, int>();
            foreach (var entry in getTags(type))
            {
                dic.Add(entry.name, entry.count);
            }
            return dic;
        }

        /// <summary>
        /// Sorts the list of tags based on how much they are used.
        /// </summary>
        private void SortList(tagType type)
        {
            SortedDictionary<string, int> dic = CreateRawList(type);
            int max = 0;
            foreach (int value in dic.Values)
            {
                if (value > max)
                    max = value;
            }

            foreach (string key in dic.Keys)
            {
                if (dic[key] < MinimumPosts)
                    continue;

                double weight = ((double)dic[key] / max) * 100;
                if (weight >= 99)
                    _WeightedList.Add(key, "biggest");
                else if (weight >= 70)
                    _WeightedList.Add(key, "big");
                else if (weight >= 40)
                    _WeightedList.Add(key, "medium");
                else if (weight >= 20)
                    _WeightedList.Add(key, "small");
                else if (weight >= 3)
                    _WeightedList.Add(key, "smallest");
            }
        }
        /// <summary>
        /// Renders the control.
        /// </summary>
        public string RenderControl()
        {
            StringBuilder sb = new StringBuilder();
            if (_WeightedList.Keys.Count == 0)
            {
                sb.Append("<p></p>");
            }

            sb.Append("<ul id=\"tagcloud\" class=\"tagcloud\">");
            foreach (string key in _WeightedList.Keys)
            {
                sb.Append("<li>");
                sb.Append(string.Format(LINK, "/listings?tag=/" + HttpUtility.UrlEncode(key), _WeightedList[key], "Tag: " + key, key));
                sb.Append("</li>");
            }

            sb.Append("</ul>");
            sb.Append("<br/>");
            return sb.ToString();
        }
#if AZURE
        private static List<tagCount> getTags(tagType type)
        {
            // TODO : AZURE tags
            return new List<tagCount>();
        }
#else
        private static List<tagCount> getTags(tagType type)
        {
            using (var db = RayaDataContext.DB())
            {
                var data = from c in db.tags_counts
                           join t in db.tags on c.tagid equals t.id
                           where t.type == (int)type
                           group c by new {t.name}
                           into mygroup
                               select new tagCount { name = mygroup.Key.name, count = mygroup.Count() };
                return data.ToList();
            }
        }
#endif

    }
}